/**
 * Copyright © 2011 looty - Textoo
 * @link http://www.textoo.org
 * @link http://code.google.com/p/textoo/
 * @author lab9 - Bertrand Larrieu
 * @mail lab9.fr@gmail.com
 * @version 2.0
 */

package org.looty.core.textoo.format 
{
	import flash.geom.*;
	import flash.text.*;
	import org.looty.core.textoo.context.style.*;
	import org.looty.textoo.font.*;
	import org.looty.textoo.format.*;

	public class RichTextFormater
	{
		
		private var _styledTF			:TextField;
		private var _richTF				:TextField;
		
		private var _styleSheet			:TextooStyleSheet;
		
		public function RichTextFormater() 
		{
			_styledTF = new TextField();			
			_styledTF.multiline = true;
			_styledTF.selectable = false;
			_styledTF.antiAliasType = AntiAliasType.ADVANCED;
			_styledTF.gridFitType = GridFitType.PIXEL;			
			
			_richTF = new TextField();
			_richTF.multiline = true;
			_richTF.selectable = false;
			_richTF.antiAliasType = AntiAliasType.ADVANCED;
			_richTF.gridFitType = GridFitType.PIXEL;
		}
		
		private function applyProperties(textField:TextField, props:TextooProps):void
		{
			textField.autoSize = TextFieldAutoSize.NONE;
			textField.text = "";
			
			textField.width = props.width - 2; //add a 2 pixel gutter on the right. seems to be missing.
			textField.height = props.height;
			textField.wordWrap = props.wordWrap;
		}
		
		private function applyHtml(textField:TextField, props:TextooProps):void
		{
			textField.htmlText = props.htmlText;
			textField.autoSize = TextFieldAutoSize.LEFT;
		}
		
		private function applyRichText(textField:TextField, props:TextooProps):void
		{
			textField.insertXMLText(0, 0, props.richTextFill);
			textField.autoSize = TextFieldAutoSize.LEFT;
		}
		
		private function testEmbededFont(textField:TextField, props:TextooProps):void
		{
			if (!props.useDeviceFonts) return;
			
			var textRun:TextRun;
			var textRuns:Array = textField.getTextRuns();
			var isEmbed:Boolean = true;
			
			while ((textRun = textRuns.shift()) != null && isEmbed) isEmbed &&= FontUtils.hasEmbeddedFont(textRun.textFormat) || /^\s+$/.test(textField.text.substring(textRun.beginIndex, textRun.endIndex));
			
			props.setEmbedFonts(isEmbed);
			textField.embedFonts = isEmbed;
		}
		
		private function retrieveRichText(textField:TextField, props:TextooProps):void
		{
			textField.width;
			textField.height; //hack, else seems like autoSize is not applied
			
			//textField.autoSize = TextFieldAutoSize.NONE;
			
			var w:Number = textField.width;
			var nw:Number;
			var h:Number = 2;
			var nh:Number;
			var lm:TextLineMetrics;
			var bd:Rectangle;
			
			var nl:int = textField.numLines;
			
			if (props.maxLines != 0 && props.maxLines < nl) nl = props.maxLines;
			
			for (var i:int = 0; i < nl; ++i) 
			{
				bd = textField.getCharBoundaries(textField.getLineOffset(i));
				lm = textField.getLineMetrics(i);
				
				if (bd != null) nh = bd.y + lm.height;
				else nh = h + lm.height + 2;
				
				if (nh + 2 > props.limits.height) break;
				h = nh;				
				
				bd = textField.getCharBoundaries(textField.getLineOffset(i) + textField.getLineLength(i) - 1);
				nw = bd != null ? bd.x + bd.width : lm.width + 4;
				
				if (nw > props.limits.width) w = props.limits.width;
				else if (nw > w) w = nw;
			}
			
			props.setSize(w is int ? w : int (w + 1), h is int ? h + 2 : int(h + 3));
			
			if (i == textField.numLines) 
			{
				props.format(textField.getXMLText(), textField.text, false, "<flashrichtext version=\"1\"/>", 0);
				return;
			}
			
			var overflowIndex:int = textField.getLineOffset(i);
			
			if (overflowIndex == 0)
			{
				props.format("<flashrichtext version=\"1\"/>", "", false, "<flashrichtext version=\"1\"/>", 0);
				return;
			}
			
			var endIndex:int = overflowIndex - 1;
			
			while (/\s/.test(textField.text.charAt(overflowIndex))) ++ overflowIndex;
			
			props.format(textField.getXMLText(0, endIndex), textField.text.substring(0, endIndex), true, textField.getXMLText(overflowIndex), overflowIndex);
		}
		
		public function format(props:TextooProps):void
		{
			switch(props.isHtml)
			{
				case true:
					applyProperties(_styledTF, props);
					applyHtml(_styledTF, props);
					testEmbededFont(_styledTF, props);			
					retrieveRichText(_styledTF, props);
				break;
				
				case false:
					applyProperties(_richTF, props);
					applyRichText(_richTF, props);		
					_richTF.embedFonts = props.embedFonts;
					retrieveRichText(_richTF, props);
				break;
			}
		}
		
		public function get styleSheet():StyleSheet 
		{
			return _styledTF.styleSheet;
		}
		
		public function set styleSheet(value:StyleSheet):void 
		{
			_styledTF.styleSheet = value;
		}		
	}
}